package com.projles.ttd.minigames;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnKeyListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;

import com.projles.ttd.OpcoesActivity;
import com.projles.ttd.R;
import com.projles.ttd.util.Expressao;
import com.projles.ttd.util.Jogador;
import com.projles.ttd.util.Player;

public class MiniGameCalculadoraActivity extends Activity {

	private Random gerador = new Random();
    private Expressao expressaoGerada = null;
    private Integer numeroRodadas;
    private Integer NUM_RODADAS_DEFAULT = 3;
    private final long TEMPO_LIMITE_PARA_RESPONDER = 15000; //em milisegundos

    private List<Jogador> jogadores = new ArrayList<Jogador>();

    private Integer indiceJogadorAtual;
    private Jogador jogadorAtual;
    
    private CountDownTimer countdown;
    private TextView countdownView;
    private EditText entrada;
    private TextView saudacao;
    private TextView status;
    private TextView expressao;
    private View viewParaAnimar;
    
    private Player player;
    
    private boolean travado = false;
    
    @SuppressWarnings("unchecked")
	@Override
    public void onCreate(Bundle savedInstanceState) {
    	super.onCreate(savedInstanceState);
    	
    	player = Player.getPlayer(this);

    	//Pegando os parametros da Intent passados na Activity anterior
    	Bundle params = getIntent().getExtras();
    	
    	jogadores = (ArrayList<Jogador>) params.get("jogadores");
    	indiceJogadorAtual = -1;
    	
    	SharedPreferences config = getSharedPreferences(OpcoesActivity.PREFS_NAME, 0);
        numeroRodadas = config.getInt("num_rodadas", NUM_RODADAS_DEFAULT);
    	
    	limpaPontuacaoJogadores();
    	
    	
    }

    
    @Override
    public void onStart() {
    	super.onStart();
    	
    	setContentView(R.layout.minigame_calculadora);
    	
    	atualizarJogadorAtual();
    	carregaViews();
    	configuraCronometro();
    	atribuiAcaoEntrada();
    	
    	animarEntradaView();
    	
    	Expressao expressaoGerada = gerarExpressaoAleatoria();
    	
    	countdownView.setTextColor(Color.WHITE);
    	saudacao.setText(getResources().getString(R.string.txt_jogador_vez) +" "+ jogadores.get(indiceJogadorAtual).getNome());
    	status.setText( getResources().getString(R.string.txt_erros) +" "+ jogadorAtual.getErros() +"  "+ getResources().getString(R.string.txt_acertos) +" "+ jogadorAtual.getAcertos());
    	expressao.setText(expressaoGerada.toString() + " = ");
    	entrada.setText("");
    	
    	if (!travado) {
			countdown.start();
			mostrarTeclado();
		}
    	
    }

    
    @Override
	public void onStop() {
		countdown.cancel();
		travado = true;
		super.onStop();
	}
	
	
	
	@Override
	protected void onDestroy() {
		countdown.cancel();
		travado = true;
		super.onDestroy();
	}

	@Override
	protected void onPause() {
		countdown.cancel();
		travado = true;
		super.onPause();
	}
    
	private void carregaViews() {
		countdownView = (TextView) findViewById(R.id.countdown_calculadora);
    	saudacao = (TextView) findViewById(R.id.saudacao);
    	status = (TextView) findViewById(R.id.status);
    	expressao = (TextView) findViewById(R.id.expressao);
    	entrada = (EditText) findViewById(R.id.resultado);
    	viewParaAnimar = findViewById(R.id.layout_mais_externo);
	}

	private void atribuiAcaoEntrada() {
		
		entrada.requestFocus();
		
		entrada.setOnKeyListener(new OnKeyListener() {
        	@Override
        	public boolean onKey(View v, int keyCode, KeyEvent event) {
                // O usuario apertar Enter no nosso EditText
                if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {

                	if (entrada.getText().length() == 0) {
                		return false;
                	}
                	
                	try {
                		Integer.valueOf(entrada.getText().toString());
                	} catch (Exception e) {
						return false;
					}
                	
                	countdown.cancel();

                	esconderTeclado();
                	
                	if (usuarioAcertou(entrada)) {
                	  jogadorAtual.acertou();
                	  player.excellent();
                	  
                	  setContentView(R.layout.acertou);
                	  
                	  Handler handler = new Handler(); 
                	  handler.postDelayed(new Runnable() { 
                		  public void run() {
                			  novaRodada();
                		  } 
                	  }, 1000); 
                	  
                	} else {
                	  jogadorAtual.errou();
                	  player.doh();
                	  
                	  setContentView(R.layout.errou);
                	  
                	  Handler handler = new Handler(); 
                	  handler.postDelayed(new Runnable() { 
                		  public void run() {
                			  novaRodada();
                		  } 
                	  }, 1000); 
                	  
                	}
                	
                	return true;
                }
                return false;
        	}
    	});
	}

	private void configuraCronometro() {
		countdown = new CountDownTimer(TEMPO_LIMITE_PARA_RESPONDER, 500) {
			
    			@Override
    			public void onTick(long tempoRestante) {
    				countdownView.setText(getResources().getString(R.string.txt_tempo) +" "+ tempoRestante/1000);
    				if (tempoRestante/1000 < 4) {
    					countdownView.setTextColor(Color.RED);
    				}
    			}
    			
    			@Override
    			public void onFinish() {
    				
    				esconderTeclado();
    				
    				jogadorAtual.errou();
    				player.doh();
    				
    				setContentView(R.layout.fim_do_tempo);
    				
    				Handler handler = new Handler(); 
    				handler.postDelayed(new Runnable() { 
    					public void run() {
    						novaRodada();
    					} 
    				}, 1000);
    			}
       	};
	}
    
    
    private void limpaPontuacaoJogadores() {
		
    	for(Jogador j : jogadores) {
    		j.zerarErrosAcertos();
    	}
	}
    
    private void atualizarJogadorAtual() {
    	if (indiceJogadorAtual == jogadores.size() - 1) {
    		indiceJogadorAtual = 0;
    	} else {
    		indiceJogadorAtual++;
    	}
    	
    	jogadorAtual = jogadores.get(indiceJogadorAtual);
    }
    
    private void novaRodada() {
    	if (!terminou()) {
    		countdown.cancel();
    		onStart();
      	} else {
      		resultadoJogo();
    	}
    }

	private void finalizaMinigame() {
		// retornando a lista de jogadores atualizada
		Intent i = this.getIntent();
		i.putExtra("listaAtualizada", (Serializable) jogadores);
		this.setResult(RESULT_OK, i);

		finish();
	}
    
    
	private boolean terminou() {
    	if (jogadorAtual.equals(jogadores.get(jogadores.size() - 1))) {
    		Integer numRodadas = jogadorAtual.getAcertos() + jogadorAtual.getErros();
    		
    		//Se o ultimo jogador da sequencia tiver jogado NUM_RODADAS vezes
    		if (numRodadas == numeroRodadas) {
    			return true; 
    		}
    	}
    	return false;
    }
    
	private void esconderTeclado() {
		InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		imm.hideSoftInputFromWindow(entrada.getWindowToken(), 0);
	}
	
	private void mostrarTeclado() {
		InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);
	}
	
	

    private void animarEntradaView() {
    	Animation in = AnimationUtils.makeInChildBottomAnimation(this);
    	viewParaAnimar.startAnimation(in);
    	viewParaAnimar.setVisibility(View.VISIBLE);
	}
    
    private void resultadoJogo(){
    	
    	boolean empate = false;
    	
    	Jogador jogadorQueErrouMais = jogadores.get(0);
    	
    	for (int i = 1; i < jogadores.size(); i++) {

    		Jogador j = jogadores.get(i); 
    		
    		if (j.getErros() > jogadorQueErrouMais.getErros()) {
    			empate = false;
    			jogadorQueErrouMais = j;
    		}
    		else if (j.getErros() == jogadorQueErrouMais.getErros()) {
    			empate = true;
    		}
			
		}
    	
    	
    	if (empate) {

    		setContentView(R.layout.tela_empate);
    		
    		Handler handler = new Handler(); 
    	    handler.postDelayed(new Runnable() { 
    	         public void run() {
    	       		finalizaMinigame();
    	         } 
    	    }, 2000); 
    		
    	}
    	else {
    		jogadorQueErrouMais.addDerrota();
    		player.aplausos();
    		
    		setContentView(R.layout.tela_bebe);
    		TextView qmBebe = (TextView) findViewById(R.id.txt_qm_bebe);
    		qmBebe.setText(jogadorQueErrouMais.getNome() +"\n\n"+ getResources().getString(R.string.txt_bebe));
    		
    		Handler handler = new Handler(); 
    	    handler.postDelayed(new Runnable() { 
    	         public void run() {
    	       		finalizaMinigame();
    	         } 
    	    }, 2000); 
    		
    	}
    
    	
    	
    }
    
    private Integer divisorInteiro(Integer numerador) {
    	List<Integer> divisores = new ArrayList<Integer>();
    	
    	if (numerador == 0) {
    		Integer numeroGerado = gerador.nextInt(100);
    		while (numeroGerado == 0) {
    			numeroGerado = gerador.nextInt(100);
    		}
    		return numeroGerado;
    	}
    	
    	for (int i = 1; i <= numerador; i++) {
    		if (numerador % i == 0) {
    			divisores.add(i);
    		}
    	}
    	
    	return divisores.get(gerador.nextInt(divisores.size()));
    }
    
    private Expressao gerarExpressaoAleatoria() {
    	String operacaoAleatoria = "";
    	
    	Integer numeroAleatorio1;
    	Integer numeroAleatorio2;
    	Integer resultado;
    	
    	switch (gerador.nextInt(65536) % 4) {
    	case 0: 
    		operacaoAleatoria = "+";
    		numeroAleatorio1 = gerador.nextInt(100);
    		numeroAleatorio2 = gerador.nextInt(100);
    		resultado = numeroAleatorio1 + numeroAleatorio2;
    		break;
    	case 1:
    		operacaoAleatoria = "-";
    		numeroAleatorio1 = gerador.nextInt(100);
    		numeroAleatorio2 = gerador.nextInt(100);
    		resultado = numeroAleatorio1 - numeroAleatorio2;
    		break;
    	case 2:
    		operacaoAleatoria = "*";
    		numeroAleatorio1 = gerador.nextInt(10);
    		numeroAleatorio2 = gerador.nextInt(10);
    		resultado = numeroAleatorio1 * numeroAleatorio2;
    		break;
    	default:
    		operacaoAleatoria = "/";
    		numeroAleatorio1 = gerador.nextInt(100);
    		numeroAleatorio2 = divisorInteiro(numeroAleatorio1);
    		resultado = numeroAleatorio1 / numeroAleatorio2;
    		break;
    	}
    	
    	expressaoGerada = new Expressao(numeroAleatorio1, operacaoAleatoria, numeroAleatorio2);
    	expressaoGerada.setResultado(resultado);
    	return expressaoGerada;
    }
    
    private boolean usuarioAcertou(EditText entrada) {
    	Integer chute = Integer.valueOf(entrada.getText().toString());
    	Integer valorExpressao = expressaoGerada.getResultado();
    	
    	if (chute.equals(valorExpressao)) {
    		return true;
    	}
    	return false;
    }
}